unit uniAudio;

interface

uses
  sdl,
  Classes;

const
  NUM_EXPLO = 2;
  NUM_EXPLO_POP = 6;
  MAX_MUSIC = 32;

type

  SoundType =
    (
    HeroAmmo00, //**< unused */
    PowerUp, //**< power up sound */
    Explosion, //**< standard explosion */
    ExploPop, //**< 'light' explosion */
    ExploBig, //**< deep, long explosion */
    AddLife, //**< new ship earned */
    LoseLife, //**< ship lost */
    MusicGame, //**< gameplay music */
    MusicMenu, //**< menu music */
    NumSoundTypes //**< total number of sounds available */
    );

  { Audio }

  Audio = class(TObject)
  public

    //const char	*fileNames[NumSoundTypes];	//**< base filenames for sound effects */
    fileNames: array[0..Integer(NumSoundTypes) - 1] of string;
    //SDL_CD	*cdrom; 					//**< pointer to CDROM struct. Is void* if not using SDL */
    cdrom: PSDL_CD;
    //char	musicFile[MAX_MUSIC][256];	//**< array of filenames for playlist */
    musicFile: array[0..MAX_MUSIC - 1] of string;

    musicMax: Integer; //**< max number of user-defined songs (CD or playlist) */
    musicIndex: Integer; //**< current track ( 0 < musicIndex < musicMax ) */

    constructor Create;
    destructor Destroy; override;
    {
    virtual void	update();
    virtual void	playSound(SoundType type, float *pos, int age = 0);
    virtual void	stopMusic();
    virtual void	pauseGameMusic(bool);
    virtual void	setMusicMode(SoundType);
    virtual void	setMusicVolume(float);
    virtual void	setSoundVolume(float);
    virtual void	setMusicIndex(int);
    virtual void	nextMusicIndex();

    virtual void	initSound();
    virtual void	initCDROM();
    }
    procedure update; virtual;
    procedure playSound(_type: SoundType; pos: array of Single; age: Integer = 0); virtual;
    procedure stopMusic; virtual;
    procedure pauseGameMusic(temp: boolean); virtual;
    procedure setMusicMode(temp: SoundType); virtual;
    procedure setMusicVolume(temp: Single); virtual;
    procedure setSoundVolume(temp: Single); virtual;
    procedure setMusicIndex(temp: Integer); virtual;
    procedure nextMusicIndex; virtual;

    procedure initSound; virtual;
    procedure initCDROM; virtual;
  end;

  //**
  // * node class used for 'audio queue'
  //*/
  //======================================

  { SoundInfo }

  SoundInfo = class(TObject)
  public
    _type: SoundType;
    pos: array[0..2] of Single;
    age: Integer;
    next: SoundInfo;
    back: SoundInfo;
    constructor Create; overload;
    constructor Create(t: SoundType; p: array of Single; a: Integer); overload;
    destructor Destroy; override;
  end;



implementation

uses
  uniGlobal,
  uniConfig;

{ Audio }

constructor Audio.Create;
var
  _config: Config;
begin
  _config := instance;

  fileNames[Integer(HeroAmmo00)] := 'wav/boom.wav';
  fileNames[Integer(PowerUp)] := 'wav/power.wav';
  fileNames[Integer(Explosion)] := 'wav/exploStd.wav';
  fileNames[Integer(ExploPop)] := 'wav/exploPop.wav';
  fileNames[Integer(ExploBig)] := 'wav/exploBig.wav';
  fileNames[Integer(LoseLife)] := 'wav/life_lose.wav';
  fileNames[Integer(AddLife)] := 'wav/life_add.wav';
  fileNames[Integer(MusicGame)] := 'wav/music_game.wav';
  fileNames[Integer(MusicMenu)] := 'wav/music_menu.wav';

  cdrom := nil;
  musicMax := 1;
  musicIndex := 0;

  if (_config.audioEnabled = true) then
  begin
    initCDROM;
  end;
end;

destructor Audio.Destroy;
begin
  inherited;
end;

procedure Audio.pauseGameMusic(temp: boolean);
var
  _config: Config;
  cdromStatus: TSDL_CDStatus;
begin
  _config := instance;
  if _config.audioEnabled = True then
  begin
    if Boolean(cdrom) then
    begin
      cdromStatus := SDL_CDStatus(cdrom);
      if temp and (cdromStatus = CD_PLAYING) then
        SDL_CDPause(cdrom)
      else
        if not temp and (cdromStatus = CD_PAUSED) then
          SDL_CDResume(cdrom)
        else
        begin
          //fprintf(stderr, "CDROM error in AudioOpenAL::pauseGameMusic(%d)\n", (int)status);
          Writeln('CDROM error in AudioOpenAL::pauseGameMusic(', Integer(cdromStatus), ')');
          //fprintf(stderr, "CDROM status = %d\n", cdromStatus);
          Writeln('CDROM status = ', Integer(cdromStatus), ')');
        end;
    end;
  end;
end;

procedure Audio.update;
begin

end;

procedure Audio.playSound(_type: SoundType; pos: array of Single; age: Integer);
begin

end;

procedure Audio.initCDROM;
begin
  cdrom := nil;
end;

procedure Audio.initSound;
begin

end;

procedure Audio.nextMusicIndex;
var
  i: integer;
begin
  i := musicIndex + 1;
  if i >= musicMax then i := 0;
  setMusicIndex(i);
end;

procedure Audio.setMusicIndex(temp: Integer);
var
  _config: Config;
  wasPlaying: Boolean;
  cdromStatus: TSDL_CDStatus;
begin
  _config := uniConfig.instance;
  if _config.audioEnabled = True then
  begin
    wasPlaying := False;
    if Boolean(musicMax) then
    begin
      musicIndex := temp mod musicMax;
    end;
    Writeln('Audio::setMusicIndex(', musicIndex, ')');

    if Boolean(cdrom) then
    begin
      cdromStatus := SDL_CDStatus(cdrom);
      if cdromStatus = CD_PLAYING then
      begin
        wasPlaying := True;
      end;
      if cdrom.track[musicIndex].type_ < SDL_DATA_TRACK then
      begin
        SDL_CDStop(cdrom);
        SDL_CDPlayTracks(cdrom, musicIndex, 0, 1, 0);
        if not wasPlaying then SDL_CDPause(cdrom);
      end
      else
      begin
        Writeln('track ', musicIndex, ' is data - trying next track...');
        setMusicIndex(musicIndex + 1);
      end;
    end;
  end;
end;

procedure Audio.setMusicMode(temp: SoundType);
var
  _config: Config;
  game: Global;
  cdromStatus: TSDL_CDStatus;
begin
  _config := uniConfig.instance;
  game := uniGlobal.getInstance;
  if _config.audioEnabled = True then
  begin
    if Boolean(cdrom) then
    begin
      cdromStatus := SDL_CDStatus(cdrom);
      case temp of
        MusicGame:
          begin
            if (cdromStatus = CD_PAUSED) and (not game.game_pause) then
            begin
              SDL_CDResume(cdrom);
            end;
            if cdromStatus = CD_STOPPED then
            begin
              SDL_CDPlayTracks(cdrom, musicIndex, 0, 1, 0);
              if game.game_pause then
              begin
                SDL_CDPause(cdrom);
              end;
            end;
          end;
        MusicMenu:
          begin
            if cdromStatus = CD_PLAYING then
            begin
              SDL_CDPause(cdrom);
            end;
          end;
      else
        if (cdromStatus = CD_PAUSED) and (not game.game_pause) then
        begin
          SDL_CDResume(cdrom);
        end;
        if cdromStatus = CD_STOPPED then
        begin
          SDL_CDPlayTracks(cdrom, musicIndex, 0, 1, 0);
          if game.game_pause then
          begin
            SDL_CDPause(cdrom);
          end;
        end;
      end;
    end;
  end;
end;

procedure Audio.setMusicVolume(temp: Single);
begin

end;

procedure Audio.setSoundVolume(temp: Single);
begin

end;

procedure Audio.stopMusic;
var
  _config: Config;
begin
  _config := uniConfig.instance;
  if _config.audioEnabled = True then
  begin
    if Boolean(cdrom) then SDL_CDStop(cdrom);
  end;
end;

{ SoundInfo }

constructor SoundInfo.Create;
begin
  _type := Explosion;
  pos[0] := 0.0;
  pos[1] := 0.0;
  pos[2] := 0.0;
  age := 1;
  back := nil;
  next := nil;
end;

constructor SoundInfo.Create(t: SoundType; p: array of Single; a: Integer);
begin
  _type := t;
  pos[0] := p[0];
  pos[1] := p[1];
  pos[2] := p[2];
  age := a;
  back := nil;
  next := nil;
end;

destructor SoundInfo.Destroy;
begin

  inherited;
end;

end.

